package org.feng.framework.annotation;

import com.alibaba.fastjson.JSON;
import eu.bitwalker.useragentutils.Browser;
import eu.bitwalker.useragentutils.UserAgent;
import lombok.AllArgsConstructor;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.feng.entity.pojo.Log;
import org.feng.entity.pojo.User;
import org.feng.service.AsyncService;
import org.feng.service.UserService;
import org.feng.utils.HttpUtils;
import org.feng.utils.IpUtils;
import org.feng.utils.UserUtil;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMethod;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;

/**
 * 日志注解解析
 *
 * @author feng
 */
@Aspect
@Component
@AllArgsConstructor
public class VisitLogAop {

    private final UserService userService;
    private final AsyncService asyncService;

    /**
     * 日期解析aop
     *
     * @param pjp pjp
     * @return 执行结果
     * @throws Throwable 异常
     */
    @Around("@annotation(org.feng.framework.annotation.VisitLog)")
    public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
        long start = System.currentTimeMillis();
        Log log = getLog(userService.getById(UserUtil.getUserId()), pjp);
        Object result = null;
        try {
            MethodSignature ms = (MethodSignature) pjp.getSignature();
            String name = ms.getMethod().getName();
            log.setMethod(name);
            String value = ms.getMethod().getAnnotation(VisitLog.class).value();
            log.setRemark(value);
            result = pjp.proceed();
            long end = System.currentTimeMillis();
            log.setRequestTime(String.valueOf((end - start)));
            asyncService.saveLog(log);
            return result;
        } catch (Exception e) {
            log.setLogType(2);
            asyncService.saveLog(log);
            throw e;
        }

    }

    /**
     * 构造log实体
     *
     * @param user 用户数据
     * @param pjp  pjp
     * @return 日志实体
     */
    private Log getLog(User user, ProceedingJoinPoint pjp) {
        HttpServletRequest request = HttpUtils.getRequest();
        Log log = new Log();
        log.setUsername(user.getUsername());
        log.setIp(IpUtils.getIpAddress(request));
        log.setUrl(request.getRequestURI());
        log.setRequestMethod(request.getMethod());
        if (RequestMethod.GET.name().equalsIgnoreCase(request.getMethod())) {
            String string = request.getQueryString();
            log.setParameters(string);
        } else {
            log.setParameters(JSON.toJSONString(pjp.getArgs()));
        }
        log.setLogType(1);
        log.setDeptId(user.getDeptId());
        Browser browser = UserAgent.parseUserAgentString(request.getHeader("User-Agent")).getBrowser();
        log.setBrowser(browser.getName());
        log.setDeptId(user.getDeptId());
        log.setCreateTime(LocalDateTime.now());
        return log;
    }


}
